/*
 * tests - consists of the main test functions
 *
 * Copyright (c) 2008 Varun Kumar Reddy Dodla
 * Licensed under GPL (GPL-LICENSE.txt)
 *
 * $Date: 2008-10-29 
 */

/**
 * this will perform type c tests which are described as:
 * clicking/inputting a value in an attribute triggers a set of values to be displayed for the
 * attribute.
 */
var currentForm;
var currentField;
var currentInputsLength;
var currentFormsLength;
var dependencies;


function conductTests(boolInit) {
	
	if(boolInit) {
		//init the variables
		currentForm = 0;
		currentField = 0;
		currentInputsLength = 0;
		currentFormsLength = 0;
		dependencies = new Array();

		//show message
		Ext.MessageBox.progress( 'Please wait', 'Running tests...');
		
		//run the tests
		tests();
	} else {
		
		if(currentField < currentInputsLength 
			&& currentForm < currentFormsLength) { 
			tests();
		} else {
			showDependencies();
		}
	}
}

function tests() {
	
	//update the clone
	updateClone(currentForm, currentField);

	//get the current forms in the DOM
	var iframeDoc = $('#center-iframe').contents()[0]; 
	var forms = $('form', iframeDoc);
	currentFormsLength = forms.length;
	
	
	//get the current form inputs
	var inputs = $(":input", forms[currentForm]);
	currentInputsLength = inputs.length;

	//write a switch case for each field
	//run specific test for each field
	var doCheck = false;
	switch(inputs[currentField].type) {
	case 'text':
		fireFocus(inputs[currentField]);
		if(inputs[currentField].value == "")
			//give some random input if it is empty
			fireInput(inputs[currentField], "abc");
		else
			//clear the existing input
			fireClear(inputs[currentField]);
		
		doCheck = true;
		break;
	case 'checkbox':
		//fire the click
		$(inputs[currentField]).click();
		
		doCheck = true;
		break;
	case 'radio':
		//fire the click
		$(inputs[currentField]).click();
		
		doCheck = true;
		break;
	case 'select-one':
		
		//get the number of options
		var optionsCount = inputs[currentField].options.length;
		if(optionsCount == 0) break;
		
		//select a random one excluding first one
		var random =  Math.floor(Math.random()*optionsCount);
		if(random == 0 && optionsCount > 1) random = 1;
		
		//select the option 
		inputs[currentField].options[random].selected = true;
		
		//fire the change event
		$(inputs[currentField]).change();
		
		doCheck = true;
		break;
	case 'reset':
	case 'submit':
	case 'button':
	case 'image':
		$(inputs[currentField]).click();

		doCheck = true;
		break;
	case 'textarea':
		if(inputs[currentField].value == "")
			//give some random input if it is empty
			fireInput(inputs[currentField], "abc");
		else
			//clear the existing input
			fireClear(inputs[currentField]);
		
		doCheck = true;
		break;
	case 'hidden':
		break;
	}
	
	//wait for any DOM changes to settle
	//settimeout for checks later
	if(doCheck)
		setTimeout(checks, 1000, inputs[currentField].name);
	else
		proceedTests();
			
}

function checks(inputName) {

	//check for changes in interface
	if(checkURLChanges(currentForm, currentField, inputName)) {
		log.info("Dependencies found for attribute: "+inputName);
		reloadURL(0);

	} else {

		//check the DOM changes in other attributes
		//if changes then record the dependency
		if(checkFormChanges(currentForm, currentField, inputName)) {
			log.info("Dependencies found for attribute: "+inputName);
		}
		
		//check for changes in interface
		if(checkInterfaceChanges(currentForm, currentField, inputName)) {
			log.info("Dependencies found for attribute: "+inputName);
		}

		//add changes in this attribute to the DOM Clone
		updateClone(currentField, currentField);

		//proceed with the tests
		proceedTests();
	}	

	
	
}

function proceedTests() {
	
//	console.log("Proceed with currentForm: "+currentForm
//				+ "currentFormLength: "+currentFormsLength
//				+ "currentField: "+currentField
//				+ "currentInputsLength: "+currentInputsLength);
	
	//proceed with the tests
	if(currentField < currentInputsLength-1) {
		currentField++;	
	}
	else if(currentForm < currentFormsLength) { //if no more fields then move to next form
		currentForm++;
		currentField = 0;
		
		//update the message
		Ext.MessageBox.updateProgress((currentForm)/currentFormsLength, 
				'Done form '+(currentForm)+' of '+currentFormsLength);
	}
	
	//call the wrapper function
	conductTests(false);

}

function checkFormChanges(formIndex, fieldIndex, inputName) { 
	var ret = false;
	
	var iframeDoc = $('#center-iframe').contents()[0]; 
	var currentForm = $('form', iframeDoc)[formIndex]; //the form as in current page
	var actualForm = $("form", urlDOMClone.DOMEl)[formIndex]; //the cloned DOM

	//if we cannot find the form then return
	if(!actualForm) return ret;
	
	var testInput = $(":input", currentForm)[fieldIndex];

	var fieldCount = $(":input", actualForm).length;
    var actualInputs = $(":input", actualForm);
    
    //loop thru the actual inputs and verify with the existing ones
    $.each(actualInputs, function(i,input) {

    	if(input.name != inputName) { 
    	
    	//I have found that sometimes they do not give the name attribute
    	//which is quite weird for a form attribute
    	//but just to encompass those attributes I will try an id match instead
    	var currentInput =  (input.name != "") ? $(":input[name='"+input.name+"']", currentForm)[0]
    						: ((input.id && input.id != "") ?  $(":input[id='"+input.id+"']", currentForm)[0]
    						: false);

    	if(currentInput) {
	    	
				//write a switch case for each field
				switch(input.type) {
				case 'textarea':
				case 'text':
					if(compareBasic(formIndex, currentForm.name, testInput.name, input, currentInput)) ret = true;
					if(compareText(formIndex, currentForm.name, testInput.name, input, currentInput)) ret = true;
					break;
				case 'checkbox':
					break;
				case 'submit':
					break;
				case 'button':
					break;
				case 'select':
				case 'select-one':
					if(compareBasic(formIndex, currentForm.name, testInput.name, input, currentInput)) ret = true;
					if(compareSelect(formIndex, currentForm.name, testInput.name, input, currentInput)) ret = true;
					break;
				case 'image':
					break;
				case 'hidden':
					break;
				}
	    	}
    	}
		
    }); //end of each function
    
    return ret;
}


function compareBasic(formIndex, name, testInputName, input, currentInput) {
	var ret = false;
	if(input.type == currentInput.type) {
		if(input.name != currentInput.name) {
			ret = true;
			dependencies[dependencies.length] = new Dependency(formIndex, name, 
												testInputName, input.name, currentInput.name, 3,
												"Different name for attribute at same index.");
		}
	} else {
		ret = true;
		dependencies[dependencies.length] = new Dependency(formIndex, name,
											testInputName, input.name, currentInput.name, 3,
											"Different type of attribute at same index.");
	}
	
	return ret;
}

function compareText(formIndex, name, testInputName, input, currentInput) {
	var ret = false;
	if(input.value != currentInput.value) {
		ret = true;
		dependencies[dependencies.length] = new Dependency(formIndex, name,
											testInputName, input.name, currentInput.name, 3,
											"Different values for attribute: "+input.name);
	}
	return ret;
}

function compareSelect(formIndex, name, testInputName, input, currentInput) {
	var ret = false;

	if(input.options.length != currentInput.options.length) {
		ret = true;
		dependencies[dependencies.length] = new Dependency(formIndex, name,
											testInputName, input.name, currentInput.name, 3,
											"Different number of options for attribute: "+input.name
											+". Before: "+input.options.length+" Now: "+currentInput.options.length);
	}
	
	return ret;
}


function updateClone() {
	//clone the DOM object
	var iframeDoc = $('#center-iframe').contents()[0];
	var iframeDocClone = $('body', iframeDoc).clone(true);
	
	urlDOMClone = new DOMClone(iframeDocClone);
	
	

	//update text field values in the clone
	//somehow jquery doesnot do this
	var forms = $("form", iframeDoc);
	$.each(forms, function(index, form) {
		
		var inputs = $(":input", form);
		var cloneForm = $("form", urlDOMClone.DOMEl)[index];
		var cloneInputs = $(":input", cloneForm);
		var count = 0;
		for(count = 0; count < inputs.length; count++) {
			
			switch(inputs[count].type) {
			case 'textarea':
			case 'text':
				if(inputs[count].type == cloneInputs[count].type 
				   && inputs[count].name == cloneInputs[count].name) cloneInputs[count].value = inputs[count].value;
				break;
			case 'checkbox':
				break;
			case 'submit':
				break;
			case 'button':
				break;
			case 'select': //may be check for selected index
			case 'select-one':
				break;
			case 'image':
				break;
			case 'hidden':
				break;
			}
		}
		
	});
}


function checkInterfaceChanges(formIndex, fieldIndex, fieldName) {
	var ret = false;
	
	//get the counts from the document as of now
	var actualBody = $('#center-iframe').contents()[0].body; 
	var actualHiddenCount = ($(":hidden", actualBody)).length;
	var actualTotalCount = ($("*", actualBody)).length;

	//get the counts from the clone
	var cloneHiddenCount = ($(":hidden", urlDOMClone.DOMEl)).length;
	var cloneTotalCount = ($("*", urlDOMClone.DOMEl)).length;
	
	if(actualHiddenCount != cloneHiddenCount) {
		dependencies[dependencies.length] = new Dependency(formIndex, $("form", actualBody)[formIndex].name,
				fieldName, 'interface', 'interface', 1,
				"Different number of hidden nodes. Before: "+cloneHiddenCount
				+" Now: "+actualHiddenCount);
		ret = true;
	}
	
	if(actualTotalCount != cloneTotalCount) {
		dependencies[dependencies.length] = new Dependency(formIndex, $("form", actualBody)[formIndex].name,
				fieldName, 'interface', 'interface', 1,
				"Different number of total nodes. Before: "+cloneTotalCount
				+" Now: "+actualTotalCount);
		ret = true;
	}
	
	return ret;
	
}

function checkURLChanges(formIndex, fieldIndex, fieldName) {
	var ret = false;
	
	//check access to the frame DOM
	try {
		var frameDoc = window.frames[0].document;
	}catch(e) {
		log.info("Cannot access frame DOM.");
		
		//record the dependency
		dependencies[dependencies.length] = new Dependency(formIndex, null,
				fieldName, 'interface', 'interface', 1,
				"Possible change in URL.");
		ret = true;
	}
	
	return ret;
}

